#include "gameroom.h"
#include "gameselect.h"
#include <QIcon>
#include <QPainter>
#include <QIcon>
#include <QPushButton>
#include <QFont>
#include <QSound>
#include <QPointF>
#include <QTimer>
#include <QMessageBox>
#include <QFile>
#include <QDebug>
#include <QKeySequence>

GameRoom::GameRoom(QWidget *parent) : QWidget(parent)
{
    //设置窗口的大小
    this->setFixedSize(1000,700);
    //设置窗口的图标
    this->setWindowIcon(QIcon(":res/icon.png"));
    //设置窗口的标题
    this->setWindowTitle("游戏界面");

    /////////////////////////////////////////////////////////////////////////////

    //对蛇链表进行初始化 在链表中插入一个QRectf
    Snake.push_back(QRectF(800*0.5,this->height()*0.5,snakeWidth,snakeHeight));
    moveUp();
    moveUp();

    //通过计时器来控制蛇的移动
    timer = new QTimer(this);

    //创建食物
    creatFood();
    //处理这个时间的事件
    connect(timer,&QTimer::timeout,[=](){
        //判断食物是否和蛇相交
        //这个计时器是当时间变化时就会触发所以只要时间一旦发生变化时间变化一次蛇就移动一次
        int ctn = 1;
        if(Snake.front().intersects(food))
        {
            //如果相遇就再创建一个食物
            creatFood();
            ctn+=3;
            QSound::play(":res/eatfood.wav");
        }
        while(ctn--)
        {
            switch (sDirection) {
            case snakeDirection::UP:
                moveUp();
                break;
            case snakeDirection::DOWN:
                moveDonw();
                break;
            case snakeDirection::LEFT:
                moveLeft();
                break;
            case snakeDirection::RIGHT:
                moveRight();
                break;
            }
        }
        //蛇的移动原理是先移动头再移动身体然后将把尾巴删除更新链表
        Snake.pop_back();
        //调用后，Qt会触发重绘事件，更新游戏界面显示蛇的新位置和状态。
        update();
    });

//////////////////////////////////////////////////////////////////////////////////////////////

    //设置游戏的状态创建控制状态的按钮

    QPushButton * strBtn = new QPushButton(this);
    QPushButton * stopBtn = new QPushButton(this);

    //设置按钮的位置
    strBtn->move(860,50);
    stopBtn->move(860,100);

    //设置按钮文字
    strBtn->setText("开始");
    stopBtn->setText("暂停");

    //设置字体
    QFont ft("华文行楷",20);
    strBtn->setFont(ft);
    stopBtn->setFont(ft);

    //为这两个按钮设置槽函数
    //开始按钮
    connect(strBtn,&QPushButton::clicked,[=](){
        sound = new QSound(":res/Trepak.wav");
        //实现再次点击开始按钮游戏重新开始
        //首先停止计时器,如果音乐还在播放就停止音乐
        if(btnPressed)
        {
            timer->stop();
        }
        sound->stop();
        //清理掉原本蛇内容，初始化蛇的状态
        Snake.clear();
        Snake.push_back(QRectF(800*0.5,this->height()*0.5,snakeWidth,snakeHeight));
        moveUp();
        moveUp();
        //首先设置游戏的状态
        isGameStart = true;
        //启动计时器s
        timer->start(timeSpeed);//设置的时计时器函数运行的周期就是蛇的速度
        //设置游戏的背景音乐
        sound = new QSound(":res/Trepak.wav");
        //设置音乐的循环播放
        sound->play();
        sound->setLoops(-1);
        update();
    });
    //暂停按钮
    connect(stopBtn,&QPushButton::clicked,[=](){
        //设置游戏状态停止定时器和音乐
        isGameStart = false;

        timer->stop();

        sound->stop();

    });

    //设置控制蛇的移动的按钮
    QPushButton * Up = new QPushButton(this);
    QPushButton * Down = new QPushButton(this);
    QPushButton * Left = new QPushButton(this);
    QPushButton * Right = new QPushButton(this);

    //为按钮设置快捷键
    Up->setShortcut(QKeySequence(Qt::Key_Up));
    Down->setShortcut(QKeySequence(Qt::Key_Down));
    Left->setShortcut(QKeySequence(Qt::Key_Left));
    Right->setShortcut(QKeySequence(Qt::Key_Right));

    //设置按钮的位置
    Up->move(880,290);
    Down->move(880,370);
    Left->move(840,330);
    Right->move(920,330);

    //设置按钮的图标
    Up->setIcon(QIcon(":res/fUp.png"));
    Down->setIcon(QIcon(":res/fDown.png"));
    Left->setIcon(QIcon(":res/fLeft.png"));
    Right->setIcon(QIcon(":res/fRight.png"));

    //设置按钮的大小
    Up->resize(40,40);
    Down->resize(40,40);
    Left->resize(40,40);
    Right->resize(40,40);

//    //设置按钮样式
//    QString style("");
//    style+="QPushButton:hover { color: white; }";
//    style+="QPushButton {border:0px;}";
//    Up->setStyleSheet(style);
//    Down->setStyleSheet(style);
//    Left->setStyleSheet(style);
//    Right->setStyleSheet(style);
    //关联按钮的槽函数
    connect(Up,&QPushButton::clicked,[=](){
        if(sDirection != snakeDirection::DOWN)
        {
            sDirection = snakeDirection::UP;
        }
    });

    connect(Down,&QPushButton::clicked,[=](){
        if(sDirection != snakeDirection::UP)
        {
            sDirection = snakeDirection::DOWN;
        }
    });

    connect(Left,&QPushButton::clicked,[=](){
        if(sDirection != snakeDirection::RIGHT)
        {
            sDirection = snakeDirection::LEFT;
        }
    });

    connect(Right,&QPushButton::clicked,[=](){
        if(sDirection != snakeDirection::LEFT)
        {
            sDirection = snakeDirection::RIGHT;
        }
    });

/////////////////////////////////////////////////////////////////////////////

    //设置退出按钮
    QPushButton * eixtBtn = new QPushButton(this);
    eixtBtn->move(860,630);
    eixtBtn->setText("退出");
    eixtBtn->setStyleSheet("QPushButton {color: white;background-color: #3498db;border: 2px solid #2980b9;border-radius: 20px; /* 椭圆形边框 */padding: 10px 20px;font-size: 20px;}"
                           "QPushButton:hover{background-color: #5dade2; border: 2px solid #1f618d;}");

    //创建一个消息弹窗
    QMessageBox *exitBox = new QMessageBox(this);
    QPushButton* OKbtn = new QPushButton("OK");
    QPushButton* NObtn = new QPushButton("NO");
    exitBox->addButton(OKbtn,QMessageBox::AcceptRole);
    exitBox->addButton(NObtn,QMessageBox::RejectRole);
    //为退出按钮设置一个槽函数
    connect(eixtBtn,&QPushButton::clicked,[=](){
        exitBox->show();
        QSound::play(":res/clicked.wav");
        //设置对话框的内容
        exitBox->setText("请确定是否退出游戏？");
        exitBox->setWindowTitle("退出游戏");
    });
    //Ok
    connect(OKbtn,&QPushButton::clicked,[=](){
        this->close();
        GameSelect *se = new GameSelect;
        se->setGeometry(this->geometry());
        se->show();
        QSound::play(":res/clicked.wav");
    });
    //NO
    connect(NObtn,&QPushButton::clicked,[=](){
        exitBox->close();
    });

}

/////////////////////////////////////////////////////////////////////////////

void GameRoom::paintEvent(QPaintEvent *event)
{
    (void)event;
    //绘制游戏界面
    QPainter painter(this);
// //    QPixmap pix(":res/game_room.png");
//    painter.drawPixmap(0,0,QPixmap(":res/icon.png"));
    QPixmap pixmap;
    //绘制游戏区域
    pixmap.load(":res/game_room.png");
    painter.drawPixmap(0,0,800,700,pixmap);
    //绘制控制区域和得分区域
    pixmap.load(":res/bg1.png");
    painter.drawPixmap(800,0,200,800,pixmap);

//绘制蛇：蛇头 蛇身 蛇尾
    //绘制蛇头 分为上 下 左 右 判断蛇头的方向
    if(sDirection==snakeDirection::UP)
    {
        pixmap.load(":res/up.png");
    }else if(sDirection==snakeDirection::DOWN)
    {
        pixmap.load(":res/down.png");
    }
    else if(sDirection==snakeDirection::LEFT)
    {
        pixmap.load(":res/left.png");
    }
    else if(sDirection==snakeDirection::RIGHT)
    {
        pixmap.load(":res/right.png");
    }
    //获取蛇链表的头部坐标
    auto snakehead = Snake.front();
    //绘画蛇头
    painter.drawPixmap(snakehead.x(),snakehead.y(),snakeWidth,snakeHeight,pixmap);

    //绘制蛇的身体
    for (int i = 1;i<Snake.size();i++)
    {
        //首先获取到身体的坐标
        auto snakeBd = Snake.at(i);
        pixmap.load(":res/Bd.png");
        painter.drawPixmap(snakeBd.x(),snakeBd.y(),snakeWidth,snakeHeight,pixmap);
    };

    //获取蛇尾巴的信息
    auto snakeTail = Snake.back();
    painter.drawPixmap(snakeTail.x(),snakeTail.y(),snakeWidth,snakeHeight,pixmap);

    //绘制食物
    pixmap.load(":res/food.png");
    painter.drawPixmap(food.x(),food.y(),food.width(),food.height(),pixmap);

////////////////////////////////////////////////////////////////////////////////

    //绘制出游戏的得分面板
    pixmap.load(":res/sorce_bg.png");
    painter.drawPixmap(820,450,150,70,pixmap);

    //绘制出所得分数
    QPen pen;
    pen.setColor(Qt::black);
    QFont font1("⽅正舒体", 22, QFont::ExtraLight, false);
    painter.setFont(font1);
    painter.setPen(pen);
    painter.drawText(900,500,QString::number(Snake.size()));

    int c = Snake.size();
    QFile file("C:/Users/34170/Desktop/1.txt");
    if(file.open(QIODevice::WriteOnly))
    {
        QTextStream out(&file);
        out<<c;
    }
    file.close();
    //设置游戏失败的情况
    if(isCheckFial())
    {
        QPen pen1;
        pen1.setColor(Qt::red);
        QFont font2("⽅正舒体", 50, QFont::ExtraLight);
        painter.setFont(font2);
        painter.setPen(pen1);
        painter.drawText(300,400,QString("GameOver!"));
        timer->stop();
    }

}

void GameRoom::moveUp()
{
    //分析蛇向上移动的情况
    //分析蛇移动的原理：蛇是用Qlist存储每一个节点，QList是一个动态数组数组中的元素是QRectF类型的元素
    //QRectF是用来创建一个坐标点都是浮点型的矩形,QRect中提供了一个用左上角坐标和右下角坐标构成一个矩形的构造函数
    QPointF leftUp;
    QPointF rightDown;

    //获取蛇的头节点蛇的头节点依旧是一个矩形
    auto snakeHead = Snake.front();
    //用变量表示出出蛇头的位置
    int headX = snakeHead.x();
    int headY = snakeHead.y();
    if(headY < 0)
    {
        leftUp = QPointF(headX,this->height()-snakeWidth);
    }
    else
    {
        leftUp = QPointF(headX,headY-snakeWidth);
    }
    //右下角的坐标
    rightDown = leftUp + QPointF(snakeWidth,snakeHeight);

    Snake.push_front(QRectF(leftUp,rightDown));
}

void GameRoom::moveDonw()
{
    //定义蛇向下移动后的左上和右下坐标
    QPointF leftUp;
    QPointF rightDown;

    //获取蛇的头节点蛇的头节点依旧是一个矩形
    auto snakeHead = Snake.front();
    //用变量表示出出蛇头的位置
    int headX = snakeHead.x();
    int headY = snakeHead.y();
    //分析蛇移动后的情况
    if(headY > this->height())
    {
        leftUp = QPointF(headX,0);
    }
    else
    {
//        leftUp = QPointF(headX,headY +snakeH eight);
        leftUp = snakeHead.bottomLeft();
    }
    //右下角的坐标
    rightDown = leftUp + QPointF(snakeWidth,snakeHeight);

    Snake.push_front(QRectF(leftUp,rightDown));
}

void GameRoom::moveLeft()
{
    //蛇向左移动
    QPointF leftUp;
    QPointF rightDown;

    //获取蛇的头节点蛇的头节点依旧是一个矩形
    auto snakeHead = Snake.front();
    //用变量表示出出蛇头的位置
    int headX = snakeHead.x();
    int headY = snakeHead.y();
    if(headX < 0)
    {
        leftUp = QPointF(800-snakeWidth,headY);
    }
    else
    {
        leftUp = QPointF(headX-snakeWidth,headY);
    }
    //右下角的坐标
    rightDown = leftUp + QPointF(snakeWidth,snakeHeight);

    Snake.push_front(QRectF(leftUp,rightDown));
}

void GameRoom::moveRight()
{
    //定义蛇向下移动后的左上和右下坐标
    QPointF leftUp;
    QPointF rightDown;

    //获取蛇的头节点蛇的头节点依旧是一个矩形
    auto snakeHead = Snake.front();
    //用变量表示出出蛇头的位置
    int headX = snakeHead.x();
    int headY = snakeHead.y();
    //分析蛇移动后的情况
    if(headX > 760)
    {
        leftUp = QPointF(0,headY);
    }
    else
    {
        leftUp = snakeHead.topRight();
//        leftUp = QPointF(headX + snakeWidth,headY);
    }
    //右下角的坐标
    rightDown = leftUp + QPointF(snakeWidth,snakeHeight);

    Snake.push_front(QRectF(leftUp,rightDown));
}

bool GameRoom::isCheckFial()
{
    //游戏结束的条件是蛇移动后是否碰到自己的身体
    //遍历蛇链表
    //首先获取蛇头结点的位置
    QRectF head = Snake.at(0);
    for (int i = 1;i<Snake.size();i++)
    {
        if(head==Snake.at(i))
        {
            return true;
        }
    }
    return false;
}

void GameRoom::creatFood()
{
    food = QRectF(qrand()%760,
                  qrand() %this->height(),
                  snakeWidth,snakeHeight);
}

void GameRoom::setGame(int speed)
{
    timeSpeed = speed;
}

void GameRoom::btnpressd()
{
    btnPressed = true;
}

